package com.zmn.oms.third.youshu.service.impl;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import com.zmn.common.dto2.ResponseDTO;
import com.zmn.common.utils.collection.CollectionUtil;
import com.zmn.common.utils.date.DateUtil;
import com.zmn.common.utils.number.NumberUtil;
import com.zmn.common.utils.reflect.BeanMapper;
import com.zmn.common.utils.string.StringUtil;
import com.zmn.consts.GateTypeConsts;
import com.zmn.market.dubbo.DubboConsts;
import com.zmn.market.dubbo.interfaces.market.app.AppListRemoteService;
import com.zmn.oms.business.interfaces.es.OrderPayEsBService;
import com.zmn.oms.business.interfaces.es.OrderWorkEsBService;
import com.zmn.oms.business.interfaces.messageV1.common.MessageGetSendInfoService;
import com.zmn.oms.common.constant.OrderConsts;
import com.zmn.oms.common.constant.OrderPayConsts;
import com.zmn.oms.common.constant.OrderStatusConsts;
import com.zmn.oms.common.exception.OmsBaseException;
import com.zmn.oms.model.entity.orderappbind.OrderThirdAppBind;
import com.zmn.oms.model.entity.pay.OrderPay;
import com.zmn.oms.model.entity.product.OrderProduct;
import com.zmn.oms.model.entity.serviceitem.OrderServiceItem;
import com.zmn.oms.model.entity.work.OrderWork;
import com.zmn.oms.services.interfaces.pay.OrderPayService;
import com.zmn.oms.services.interfaces.product.OrderProductService;
import com.zmn.oms.services.interfaces.serviceitem.OrderServiceItemService;
import com.zmn.oms.services.interfaces.work.OrderWorkService;
import com.zmn.oms.third.youshu.OrderSourceEnum;
import com.zmn.oms.third.youshu.YouShuConsts;
import com.zmn.oms.third.youshu.YouShuOrderConsts;
import com.zmn.oms.third.youshu.YouShuPayConsts;
import com.zmn.oms.third.youshu.dto.*;
import com.zmn.oms.third.youshu.service.YouShuService;
import com.zmn.oms.third.youshu.util.YouShuUtils;
import com.zmn.pay.common.constant.PayConsts;
import com.zmn.saas.common.dro.app.AppInfoDRO;
import com.zmn.saas.dubbo.interfaces.app.AppRemoteService;
import com.zmn.uuc.common.dro.user.UserThirdDetailDRO;
import com.zmn.uuc.dubbo.interfaces.user.UserThirdListRemoteService;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.Reference;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.filter.ParsedFilter;
import org.elasticsearch.search.aggregations.metrics.ParsedSum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 类描述：腾讯有数对接接口实现
 *
 * @author ligang
 * @date 2022/03/21 16:53
 */
@Service
@Slf4j
public class YouShuServiceImpl implements YouShuService {

    @Resource
    private OrderWorkService orderWorkService;
    @Resource
    private OrderProductService orderProductService;
    @Resource
    private OrderServiceItemService orderServiceItemService;
    @Resource
    private OrderWorkEsBService orderWorkEsBService;
    @Autowired
    private OrderPayEsBService orderPayEsBService;
    @Resource
    private MessageGetSendInfoService messageGetSendInfoService;
    @Resource
    private OrderPayService orderPayService;
    @Reference(version = com.zmn.uuc.common.constant.DubboConsts.INTERFACE_VERSION, check = false)
    private UserThirdListRemoteService userThirdListRemoteService;
    @Reference(version = DubboConsts.INTERFACE_VERSION , check = false)
    private AppListRemoteService appListRemoteService;
    @Reference(version = com.zmn.saas.dubbo.constant.SaasDubboConsts.INTERFACE_VERSION, check = false)
    private AppRemoteService appRemoteService;


    /**
     * 同步接单信息到腾讯有数
     *
     * @param orderId
     * @param workId
     * @return
     */
    @Override
    public void sendAddOrder(Long orderId, Long workId) throws OmsBaseException {
        if (!YouShuConsts.POWER_ON) {
            log.info("【{}】<同步接单信息> 该功能没有开启。", YouShuConsts.CHANNEL_NAME);
            return;
        }
        log.info("同步接单信息到腾讯有数: orderId={} workId={}", orderId, workId);
        // 参数判断
        Assert.notNull(orderId, "订单号为空");
        Assert.notNull(workId, "工单号为空");

        // 查询工单数据
        OrderWork orderWork = orderWorkService.findOrderWorkByKey(orderId, workId);
        if (Objects.isNull(orderWork)) {
            return;
        }

        // 新单
        if (Objects.equals(orderWork.getType(), OrderConsts.ORDER_TYPE_NEW)) {
            this.sendNewOrder(orderWork);
        }

        // 退款单
        if (Objects.equals(orderWork.getType(), OrderConsts.ORDER_TYPE_REFUND)) {
            this.sendReturnOrder(orderWork);
        }
    }

    /**
     * 同步订单状态信息到腾讯有数
     *
     * @param orderId
     * @param workId
     * @return
     */
    @Override
    public void sendOrderStatus(Long orderId, Long workId) throws OmsBaseException {
        if (!YouShuConsts.POWER_ON) {
            log.info("【{}】<同步订单状态信息> 该功能没有开启。", YouShuConsts.CHANNEL_NAME);
            return;
        }
        log.info("同步订单状态信息到腾讯有数: orderId={} workId={}", orderId, workId);
        // 查询工单数据
        OrderWork dbOrderWork = orderWorkService.findOrderWorkByKey(orderId, workId);

        // 组装上报内容
        List<YouShuOrderStatusDTO.Order> orderList = Lists.newArrayList();
        YouShuOrderStatusDTO.Order order = YouShuOrderStatusDTO.Order.builder()
                .externalOrderId(String.valueOf(dbOrderWork.getOrderId()))
                .orderStatus(getOrderStatus(dbOrderWork))
                .statusChangeTime(String.valueOf(DateUtil.getNow().getTime()))
                .build();
        orderList.add(order);
        YouShuOrderStatusDTO youShuOrderStatusDTO = YouShuOrderStatusDTO.builder()
                .dataSourceId(YouShuConsts.DATA_SOURCE_ID)
                .orders(orderList).build();

        // 发送消息
        YouShuResponse youShuResponse = YouShuUtils.sendRequest(YouShuConsts.ORDER_UPDATE_PUSH_URL, youShuOrderStatusDTO);

        if (Objects.isNull(youShuResponse)) {
            throw new OmsBaseException("发送同步订单状态消息失败");
        }

        // 取得返回的内容
        Integer retCode = youShuResponse.getRetCode();
        String errMsg = youShuResponse.getErrMsg();
        if (Objects.isNull(retCode) || StringUtil.isNotBlank(errMsg)) {
            log.info("腾讯有数订单状态接口上报失败: {}", JSON.toJSONString(youShuResponse));
            throw new OmsBaseException("获取返回失败消息内容");
        }
    }

    /**
     * 同步订单汇总信息到腾讯有数
     *
     * @param
     * @return
     */
    @Override
    public void sendSumOrder() throws OmsBaseException {
        if (!YouShuConsts.POWER_ON) {
            log.info("【{}】<同步订单汇总信息> 该功能没有开启。", YouShuConsts.CHANNEL_NAME);
            return;
        }
        log.info("同步订单汇总信息到腾讯有数");
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern(DateUtil.FORMAT_DEFAULT);
        LocalDate now = LocalDate.now();
        // 昨天凌晨
        LocalDateTime zeroTime = LocalDateTime.of(now, LocalTime.MIN).minusDays(1);
        // 昨天最大时间
        LocalDateTime maxTime = LocalDateTime.of(now, LocalTime.MAX).minusDays(1);

        YouShuSumOrderDTO.Order order = YouShuSumOrderDTO.Order.builder()
                .refDate(String.valueOf(zeroTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli())).build();

        // ------------------ 获取下单汇总 ------------------
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery()
                .filter(QueryBuilders.termQuery("isTest", false))
                .filter(QueryBuilders.termQuery("isDuplicate", false))
                .filter(QueryBuilders.termsQuery("type", Lists.newArrayList(OrderConsts.ORDER_TYPE_NEW)))
                .filter(QueryBuilders.rangeQuery("receiveTime").gte(dtf.format(zeroTime)).lte(dtf.format(maxTime)))
                .filter(QueryBuilders.termsQuery("channelId", Lists.newArrayList(YouShuConsts.PUSH_CHANNEL_SET)));

        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
        NativeSearchQuery build = nativeSearchQueryBuilder.withQuery(queryBuilder)
                .withPageable(Pageable.unpaged())
                // 下单量
                .addAggregation(AggregationBuilders.filter("orderCount", QueryBuilders.boolQuery()))
                // 下单金额
                .addAggregation(AggregationBuilders.filter("totalExpenseAmountFilter", QueryBuilders.boolQuery())
                        .subAggregation(AggregationBuilders.sum("totalExpenseAmountSum").field("originalAmount"))
                )
                .build();

        Aggregations orderAggregations = orderWorkEsBService.getAggregationsByQuery(build);
        long orderCount = ((ParsedFilter) orderAggregations.get("orderCount")).getDocCount();
        order.setGiveOrderNumSum((int) orderCount);
        double orderTotalAmountSum = ((ParsedSum) ((ParsedFilter) orderAggregations.get("totalExpenseAmountFilter"))
                .getAggregations().get("totalExpenseAmountSum")).getValue();
        order.setGiveOrderAmountSum(parseAmount(orderTotalAmountSum));

        // ------------------ 获取支付汇总 ------------------
        BoolQueryBuilder queryPayBuilder = QueryBuilders.boolQuery()
//                .filter(QueryBuilders.termQuery("isTest", false))
//                .filter(QueryBuilders.termQuery("isDuplicate", false))
                .filter(QueryBuilders.rangeQuery("payTime").gte(dtf.format(zeroTime)).lte(dtf.format(maxTime)))
                .filter(QueryBuilders.termsQuery("channelId", Lists.newArrayList(YouShuConsts.PUSH_CHANNEL_SET)))
                .filter(QueryBuilders.termsQuery("orderType", Lists.newArrayList(OrderConsts.ORDER_TYPE_NEW)));

        nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
        build = nativeSearchQueryBuilder.withQuery(queryPayBuilder)
                .withPageable(Pageable.unpaged())
                .addAggregation(AggregationBuilders.filter("payAmountFilter", QueryBuilders.boolQuery()
                        .filter(QueryBuilders.termQuery("tradeType", PayConsts.PAY_TRADE_TYPE_INTIME)))
                        .subAggregation(AggregationBuilders.sum("payAmountSum").field("amount"))
                )
                .build();
        Aggregations pays = orderPayEsBService.getAggregationsByQuery(build);
        long payCount = ((ParsedFilter) pays.get("payAmountFilter")).getDocCount();
        order.setPayedNumSum((int) payCount);
        double payTotalAmountSum = ((ParsedSum) ((ParsedFilter) pays.get("payAmountFilter")).getAggregations()
                .get("payAmountSum")).getValue();
        order.setPaymentAmountSum(parseAmount(payTotalAmountSum));

        YouShuSumOrderDTO youShuSumOrderDTO = YouShuSumOrderDTO.builder()
                .dataSourceId(YouShuConsts.DATA_SOURCE_ID)
                .orders(Collections.singletonList(order))
                .build();
        // 发送消息
        YouShuResponse youShuResponse = YouShuUtils.sendRequest(YouShuConsts.ORDER_SUM_PUSH_URL, youShuSumOrderDTO);

        if (Objects.isNull(youShuResponse)) {
            throw new OmsBaseException("发送同步订单汇总消息失败");
        }

        // 取得返回的内容
        Integer retCode = youShuResponse.getRetCode();
        String errMsg = youShuResponse.getErrMsg();
        if (Objects.isNull(retCode) || StringUtil.isNotBlank(errMsg)) {
            log.info("腾讯有数退款订单接口上报失败: {}", JSON.toJSONString(youShuResponse));
            throw new OmsBaseException("获取返回失败消息内容");
        }
    }

    /**
     * 新单上报
     *
     * @param orderWork
     * @throws OmsBaseException
     */
    private void sendNewOrder(OrderWork orderWork) throws OmsBaseException {
        String orderStatus = getOrderStatus(orderWork);
        if (Objects.equals(orderStatus, YouShuOrderConsts.ORDER_STATUS_PAID_DELIVERY)) {
            if (NumberUtil.isNullOrZero(orderWork.getPrepayAmount()) &&
                    NumberUtil.isNullOrZero(orderWork.getChannelPrepayAmount())) {
                log.info("同步订单状态信息到腾讯有数 预付款为0 无需上报1150: orderId={} workId={}", orderWork.getOrderId(), orderWork.getWorkId());
                return;
            }
        }
        // 获取产品信息
        List<OrderProduct> orderProducts = orderProductService.listOrderProductByOrderId(orderWork.getOrderId());
        OrderProduct orderProduct = orderProducts.get(0);
        List<OrderServiceItem> orderServiceItemList = orderServiceItemService.listByOrderId(orderWork.getOrderId());
        int price = orderServiceItemList.stream()
                .filter(e -> e.getTotalPrice() != null && Objects.equals(e.getProExtId(), orderServiceItemList.get(0).getProExtId()))
                .mapToInt(OrderServiceItem::getTotalPrice).sum();
        int sumPrice = orderServiceItemList.stream()
                .filter(e -> e.getTotalPrice() != null)
                .mapToInt(OrderServiceItem::getTotalPrice).sum();
        String orderId = String.valueOf(orderWork.getOrderId());

        // 组装上报内容
        Float goodsAmountTotal = parseAmount(sumPrice);
        Float paymentAmount = getPaymentAmount(orderWork);
        List<YouShuAddOrderDTO.GoodsInfo> goodsInfoList = Lists.newArrayList();
        YouShuAddOrderDTO.GoodsInfo goodsInfo = YouShuAddOrderDTO.GoodsInfo.builder()
                .externalSkuId(String.valueOf(orderWork.getShowProductId()))
                .skuNameChinese(orderProduct.getShowProductName())
                .goodsAmount(parseAmount(price))
                .paymentAmount(paymentAmount)
                .externalSpuId(String.valueOf(orderWork.getShowProductId()))
                .spuNameChinese(orderProduct.getShowProductName())
                .goodsNum(orderProduct.getNumber())
                .build();
        goodsInfoList.add(goodsInfo);
        YouShuAddOrderDTO.UserInfo userInfo = YouShuAddOrderDTO.UserInfo.builder().build();
        List<YouShuAddOrderDTO.Order> orderList = Lists.newArrayList();
        YouShuAddOrderDTO.Order order = YouShuAddOrderDTO.Order.builder()
                .externalOrderId(orderId)
                .createTime(String.valueOf(orderWork.getReceiveTime().getTime()))
                .orderSource(getOrderSource(orderWork))
                .orderType(this.getOrderType(orderWork))
                .goodsNumTotal(orderProduct.getNumber())
                .goodsAmountTotal(goodsAmountTotal)
                .orderAmount(goodsAmountTotal)
                .freightAmount(0.00F)
                .payableAmount(paymentAmount)
                .paymentAmount(paymentAmount)
                .orderStatus(orderStatus)
                .statusChangeTime(String.valueOf(DateUtil.getNow().getTime()))
                .userInfo(userInfo)
                .goodsInfos(goodsInfoList)
                .isDeleted(0)
                .build();
        orderList.add(order);

        if (Objects.equals(orderStatus, YouShuOrderConsts.ORDER_STATUS_UNPAID)) {
            order.setStatusChangeTime(order.getCreateTime());
        }

        // 单状态为1180时，应为订单应付金额
//        if (Objects.equals(orderStatus, YouShuOrderConsts.ORDER_STATUS_COMPLETE)) {
//            order.setPayableAmount(paymentAmount);
//        }

        // 来源渠道为微信app需要上传openid
        if (Objects.equals(order.getOrderSource(), OrderSourceEnum.WX.getCode())) {
            userInfo.setOpenId(getWeixinOpenId(orderWork.getChannelId(), orderWork.getOrderId(), orderWork.getUserId()));
        }

        // 支付方式
        List<OrderPay> orderPays = Lists.newArrayList();
        if (!Objects.equals(order.getOrderStatus(), YouShuOrderConsts.ORDER_STATUS_UNPAID)) {
            orderPays = orderPayService.listOrderPayByOrderId(orderWork.getOrderId());
            orderPays = orderPays.stream().filter(orderPay -> !Objects.equals(orderPay.getTradeType(), PayConsts.PAY_TRADE_TYPE_REFUND) &&
                    Objects.equals(orderPay.getPayStatus(), PayConsts.PAY_STATUS_DONE))
                    .collect(Collectors.toList());
            List<YouShuAddOrderDTO.PaymentInfo> paymentInfoList = Lists.newArrayList();
            boolean hasPrepayAmountPay = false;
            for (OrderPay orderPay : orderPays) {
                if (Objects.equals(orderPay.getAmountType(), OrderPayConsts.ORDER_PAY_PREPAY) ||
                        Objects.equals(orderPay.getAmountType(), OrderPayConsts.ORDER_PAY_CHANNEL_PREPAY)) {
                    hasPrepayAmountPay = true;
                }
                YouShuAddOrderDTO.PaymentInfo paymentInfo = YouShuAddOrderDTO.PaymentInfo.builder()
                        .paymentType(getPaymentType(orderPay))
                        .transId(StringUtil.isBlank(orderPay.getPayOutTradeNo()) ? orderId : orderPay.getPayOutTradeNo())
                        .outTradeNumber(orderId)
                        .transAmount(parseAmount(orderPay.getAmount()))
                        .build();
                paymentInfoList.add(paymentInfo);
            }
            // 有预付 无支付记录塞现金支付
            if (!hasPrepayAmountPay) {
                if (NumberUtil.isNotNullOrZero(orderWork.getPrepayAmount()) ||
                        NumberUtil.isNotNullOrZero(orderWork.getChannelPrepayAmount())) {
                    YouShuAddOrderDTO.PaymentInfo paymentInfo = YouShuAddOrderDTO.PaymentInfo.builder()
                            .paymentType(YouShuPayConsts.PAY_TYPE_CASH)
                            .transId(orderId)
                            .outTradeNumber(orderId)
                            .transAmount(parseAmount(NumberUtil.isNotNullOrZero(orderWork.getPrepayAmount()) ? orderWork.getPrepayAmount() : orderWork.getChannelPrepayAmount()))
                            .build();
                    paymentInfoList.add(paymentInfo);
                }
            }
            order.setPaymentInfos(paymentInfoList);
        }

        YouShuAddOrderDTO youShuAddOrderDTO = YouShuAddOrderDTO.builder()
                .dataSourceId(YouShuConsts.DATA_SOURCE_ID)
                .orders(orderList).build();
        List<YouShuAddOrderDTO> youShuAddOrderDTOS = Lists.newArrayList(youShuAddOrderDTO);

        // 完成后重新上报1150
        if (orderWork.getStatus() >= OrderStatusConsts.WORK_STATUS_COMPLETE) {
            YouShuAddOrderDTO shuAddOrderDTO = BeanMapper.map(youShuAddOrderDTO, YouShuAddOrderDTO.class);
            shuAddOrderDTO.getOrders().get(0).setOrderStatus(YouShuOrderConsts.ORDER_STATUS_PAID_DELIVERY);
            Optional<OrderPay> orderPayOptional = orderPays.stream().filter(e ->
                    Objects.equals(e.getAmountType(), OrderPayConsts.ORDER_PAY_MASTER))
                    .filter(e -> Objects.equals(e.getPayChannelId(), PayConsts.PAY_CHANNEL_PLATFORM_BANKTRANSFER)
                            || Objects.equals(e.getPayType(), PayConsts.PAY_TYPE_APP))
                    .findAny();
            if (orderPayOptional.isPresent()) {
                shuAddOrderDTO.getOrders().get(0).setOrderSource(OrderSourceEnum.SELF.getCode());
            }
            youShuAddOrderDTOS.add(shuAddOrderDTO);
        }

        for (YouShuAddOrderDTO dto : youShuAddOrderDTOS) {

            // 发送消息
            YouShuResponse youShuResponse = YouShuUtils.sendRequest(YouShuConsts.ORDER_ADD_PUSH_URL, dto);

            if (Objects.isNull(youShuResponse)) {
                throw new OmsBaseException("发送同步接受订单状态消息失败");
            }

            // 取得返回的内容
            Integer retCode = youShuResponse.getRetCode();
            String errMsg = youShuResponse.getErrMsg();
            if (Objects.isNull(retCode) || StringUtil.isNotBlank(errMsg)) {
                log.info("腾讯有数订单接口上报失败: {}", JSON.toJSONString(youShuResponse));
                throw new OmsBaseException("获取返回失败消息内容");
            }
        }
    }

    /**
     * 同步退款订单信息到腾讯有数
     *
     * @param orderWork
     * @return
     */

    private void sendReturnOrder(OrderWork orderWork) throws OmsBaseException {
        // 组装上报内容
        List<YouShuReturnOrderDTO.ReturnGoodsInfo> goodsInfoList = Lists.newArrayList();
        List<OrderProduct> orderProducts = orderProductService.listOrderProductByOrderId(orderWork.getOrderId());
        OrderWork originalOrderWork = orderWorkService.findOrderWorkByKey(orderWork.getOriginalId(), orderWork.getOriginalId());
        OrderProduct orderProduct = orderProducts.get(0);
        YouShuReturnOrderDTO.ReturnGoodsInfo goodsInfo = YouShuReturnOrderDTO.ReturnGoodsInfo.builder()
                .externalSkuId(String.valueOf(orderWork.getShowProductId()))
                .skuNameChinese(orderProduct.getShowProductName())
                .externalSpuId(String.valueOf(orderWork.getShowProductId()))
                .spuNameChinese(orderProduct.getShowProductName())
                .returnGoodsAmount(parseAmount(originalOrderWork.getTotalAmount()))
                .returnGoodsNum(orderProduct.getNumber())
                .build();
        goodsInfoList.add(goodsInfo);

        List<YouShuReturnOrderDTO.Order> orderList = Lists.newArrayList();
        YouShuReturnOrderDTO.Order order = YouShuReturnOrderDTO.Order.builder()
                .externalReturnOrderId(String.valueOf(orderWork.getRefundWorkId()))
                .externalOrderId(String.valueOf(orderWork.getOrderId()))
                .returnCreateTime(String.valueOf(orderWork.getReceiveTime().getTime()))
                .returnNum(1)
                .returnAmount(parseAmount(orderWork.getRefundAmount()))
                .returnOrderAmount(parseAmount(orderWork.getRefundAmount()))
                .returnFreightAmount(0.00F)
                .returnOrderStatus(getOrderStatus(orderWork))
                .statusChangeTime(String.valueOf(DateUtil.getNow().getTime()))
                .returnGoodsInfos(goodsInfoList)
                .build();
        orderList.add(order);
        YouShuReturnOrderDTO youShuAddOrderDTO = YouShuReturnOrderDTO.builder()
                .dataSourceId(YouShuConsts.DATA_SOURCE_ID)
                .orders(orderList).build();

        // 发送消息
        YouShuResponse youShuResponse = YouShuUtils.sendRequest(YouShuConsts.ORDER_RETURN_PUSH_URL, youShuAddOrderDTO);

        if (Objects.isNull(youShuResponse)) {
            throw new OmsBaseException("发送同步退款订单状态消息失败");
        }

        // 取得返回的内容
        Integer retCode = youShuResponse.getRetCode();
        String errMsg = youShuResponse.getErrMsg();
        if (Objects.isNull(retCode) || StringUtil.isNotBlank(errMsg)) {
            log.info("腾讯有数退款订单接口上报失败: {}", JSON.toJSONString(youShuResponse));
            throw new OmsBaseException("获取返回失败消息内容");
        }
    }

    /**
     * 获取订单来源
     *
     * @param orderWork
     * @return
     */
    private String getOrderSource(OrderWork orderWork) {
        switch (orderWork.getReceiveEntranceType()) {
            case GateTypeConsts.GATE_APP_PRIMARY_ANDROID:
            case GateTypeConsts.GATE_APP_PRIMARY_IOS:
            case GateTypeConsts.GATE_APP_MASTER_ANDROID:
            case GateTypeConsts.GATE_APP_MASTER_IOS:
            case GateTypeConsts.GATE_TYPE_APP:
                return OrderSourceEnum.APP.getCode();
            case GateTypeConsts.GATE_WECHAT_SITE:
            case GateTypeConsts.GATE_PRIMARY_H5:
            case GateTypeConsts.GATE_WECHAT_H5_OLD:
                return OrderSourceEnum.H5.getCode();
            case GateTypeConsts.GATE_WECHAT_MINI:
            case GateTypeConsts.GATE_TYPE_WECHAT:
                return OrderSourceEnum.WX.getCode();
            case GateTypeConsts.GATE_PRIMARY_PC:
            case GateTypeConsts.GATE_PLAT_CC:
            case GateTypeConsts.GATE_PLAT_CHAT:
            case GateTypeConsts.GATE_PLAT_BACKSTAGE:
                return OrderSourceEnum.PC.getCode();
            default:
                return OrderSourceEnum.OTHER.getCode();
        }
    }

    /**
     * 获取订单类型
     *
     * @param orderWork
     * @return
     */
    private Integer getOrderType(OrderWork orderWork) {
        if (orderWork.getStatus() >= OrderStatusConsts.WORK_STATUS_COMPLETE) {
            return YouShuOrderConsts.ORDER_TYPE_FINAL_PAYMENT;
        }
        return YouShuOrderConsts.ORDER_TYPE_PREPAID;
    }

    /**
     * 商品总金额
     *
     * @param orderWork
     * @return
     */
    private Float getGoodsAmountTotal(OrderWork orderWork) {
        // 1、添加时，传：订单原价；若订单无原价但有预付款，传：预付款金额
        Integer amount = 0;
        // 2、订单完成后，更新订单数据，传：订单原价
        if (NumberUtil.isNotNullOrZero(orderWork.getOriginalAmount())) {
            amount = orderWork.getOriginalAmount();
        }
        if (orderWork.getStatus() <= OrderStatusConsts.ORDER_STATUS_COMPLETE) {
            if (NumberUtil.isNotNullOrZero(orderWork.getPrepayAmount())) {
                amount = orderWork.getPrepayAmount();
            } else if (NumberUtil.isNotNullOrZero(orderWork.getChannelPrepayAmount())) {
                amount = orderWork.getChannelPrepayAmount();
            }
        }
        return parseAmount(amount);
    }


    /**
     * 获取订单应付金额
     *
     * @param orderWork
     * @return
     */
    private Float getPaymentAmount(OrderWork orderWork) {
        Integer amount = null;
        if (NumberUtil.isNotNullOrZero(orderWork.getTotalAmount())) {
            amount = orderWork.getTotalAmount();
        } else if (NumberUtil.isNotNullOrZero(orderWork.getPrepayAmount())) {
            amount = orderWork.getPrepayAmount();
        } else if (NumberUtil.isNotNullOrZero(orderWork.getChannelPrepayAmount())) {
            amount = orderWork.getChannelPrepayAmount();
        }
        return parseAmount(amount);
    }

    /**
     * 获取支付方式
     *
     * @param orderPay
     * @return
     */
    private String getPaymentType(OrderPay orderPay) {
        if (Objects.equals(orderPay.getAmountType(), OrderPayConsts.ORDER_PAY_DISCOUNT)) {
            return YouShuPayConsts.PAY_TYPE_DISCOUNT;
        }
        switch (orderPay.getPayChannelId()) {
            case PayConsts.PAY_CHANNEL_PLATFORM_WEIXINPAY:
                return YouShuPayConsts.PAY_TYPE_WEIXIN;
            case PayConsts.PAY_CHANNEL_PLATFORM_ALIPAY:
                return YouShuPayConsts.PAY_TYPE_ZFB;
            default:
                return YouShuPayConsts.PAY_TYPE_CASH;
        }
    }

    /**
     * 获取订单状态
     *
     * @param orderWork
     * @return
     */
    private String getOrderStatus(OrderWork orderWork) throws OmsBaseException {
        log.info("#YouShuServiceImpl#getOrderStatus: orderId={} status={} resultStatus={} payStatus={}",
                orderWork.getOrderId(), orderWork.getStatus(), orderWork.getResultStatus(), orderWork.getPayStatus());
        int status = orderWork.getStatus();
        int payStatus = orderWork.getPayStatus();
        int resultStatus = orderWork.getResultStatus();
        int type = orderWork.getType();
        String youShuOrderStatus = YouShuOrderConsts.getYouShuOrderStatus(status, type, payStatus, resultStatus);
        if (StringUtil.isBlank(youShuOrderStatus)) {
            throw new OmsBaseException("映射订单状态失败");
        }
        return youShuOrderStatus;
    }

    /**
     * 统一转换成元，保留两位小数
     *
     * @param amount
     */
    private Float parseAmount(Integer amount) {
        if (NumberUtil.isNullOrZero(amount)) {
            return 0.00F;
        }
        BigDecimal b1 = new BigDecimal(amount);
        BigDecimal b2 = new BigDecimal(100);
        return b1.divide(b2, 2, RoundingMode.HALF_UP).floatValue();
    }

    /**
     * 统一转换成元，保留两位小数
     *
     * @param amount
     */
    private Float parseAmount(Double amount) {
        if (NumberUtil.isNullOrZero(amount)) {
            return 0.00F;
        }
        BigDecimal b1 = BigDecimal.valueOf(amount);
        BigDecimal b2 = new BigDecimal(100);
        return b1.divide(b2, 2, RoundingMode.HALF_UP).floatValue();
    }

    /**
     * 通过用户id，查找并设置微信消息里小程序数据
     *
     * @param channel
     * @param orderId
     * @param userId
     * @return
     */
    private String getWeixinOpenId(Integer channel, Long orderId, Long userId) {
        try {
            // 通过用户Id查找关联的第三方
            log.info("orderId[{}]#YouShuServiceImpl#getWeixinOpenId#UserThirdListRemoteService#listThirdByUserId# 入参{}", orderId, userId);
            ResponseDTO<List<UserThirdDetailDRO>> listResponseDTO = userThirdListRemoteService.listThirdByUserId(userId);
            log.info("orderId[{}]#YouShuServiceImpl#getWeixinOpenId#UserThirdListRemoteService#listThirdByUserId# 出参{}", orderId, listResponseDTO);
            if (!listResponseDTO.isSuccess() || CollectionUtil.isNullOrEmpty(listResponseDTO.getData())) {
                return null;
            }
            log.info("orderId[{}]#YouShuServiceImpl#getWeixinOpenId#appListRemoteService#getShowAppByChannelIdOrShopId# 入参{}", orderId, channel);
            ResponseDTO<AppInfoDRO> appInfoDRO = appRemoteService.getShowAppByChannelIdOrShopId(channel, null);
            log.info("orderId[{}]#YouShuServiceImpl#getWeixinOpenId#appListRemoteService#getShowAppByChannelIdOrShopId# 出参{}", orderId, appInfoDRO);
            if (!appInfoDRO.isSuccess() || Objects.isNull(appInfoDRO.getData())) {
                return null;
            }
            return listResponseDTO.getData().stream().filter(e -> Objects.equals(e.getAppId(), appInfoDRO.getData().getThirdAppId())).findAny().get().getOpenId();
        } catch (Exception e) {
            log.error("#YouShuServiceImpl#getWeixinOpenId 获取微信用户openId失败:{}", e);
        }
        return null;
    }
}
